package com.such.kit.database.dialect;

import java.util.List;
import com.such.kit.database.bean.Page;
import com.such.kit.easyparam.ParamMap;
import com.such.kit.placeholder.PlaceholderCommons;
import com.such.kit.resource.support.ReadResource;
import com.such.kit.string.StringCommons;
import com.such.kit.validate.ValidateCommons;

/**
 * @作者 SUCH
 * @日期 2017-10-12 下午4:41:58
 * @描述 SQL 语句工厂
 * <p>resourceKey 默认为方法名，占位符默认为参数名</p>
 */
public class SqlFactory {

	private String resourceName;

	public SqlFactory(String resourceName) {
		this.resourceName = resourceName;
	}

	/**
	 * <p>方法名：buildDummyTableSql</p>
	 * <p>描述：构建伪表查询</p>
	 * @param sqlFragment sql 片段
	 * @return 伪表查询
	 */
	public String buildDummyTableSql(String sqlFragment) {
		String dummyTableSql = ReadResource.getValue(this.resourceName, "buildDummyTableSql");
		dummyTableSql = PlaceholderCommons.replacePlaceholder(dummyTableSql, new ParamMap<String, String>()
				.putParam("sqlFragment", sqlFragment));
		return dummyTableSql;
	}

	/**
	 * <p>方法名：buildSequenceNextValueSql</p>
	 * <p>描述：构建获取下个序列值语句（不包括伪表查询）</p>
	 * @param sequenceName 序列名称
	 * @param alias 值别名，可为空，默认值为 NEXT_VALUE
	 * @return 获取下个序列值语句
	 */
	public String buildSequenceNextValueSql(String sequenceName, String alias) {
		if (ValidateCommons.isEmpty(alias)) {
			alias = "NEXT_VALUE";
		}

		String sequenceNextValueSql = ReadResource.getValue(this.resourceName, "buildSequenceNextValueSql");
		sequenceNextValueSql = PlaceholderCommons.replacePlaceholder(sequenceNextValueSql, new ParamMap<String, String>()
				.putParam("sequenceName", sequenceName)
				.putParam("alias", alias));
		return sequenceNextValueSql;
	}

	/**
	 * <p>方法名：buildCallSql</p>
	 * <p>描述：构建 call 语句，用于调用存储过程、函数等</p>
	 * @param callName call 的对象名
	 * @param params 参数列表，需要进行参数绑定可以传入 ?，直接传入值需要自行根据类型判断是否需要使用 '#[val]'
	 * @return call 语句
	 */
	public String buildCallSql(String callName, List<String> params) {
		String paramsString = "";
		if (ValidateCommons.isNotEmpty(params)) {
			paramsString = StringCommons.merger(params.toArray(), ", ", true);
		}

		String callSql = ReadResource.getValue(this.resourceName, "buildCallSql");
		callSql = PlaceholderCommons.replacePlaceholder(callSql, new ParamMap<String, String>()
				.putParam("callName", callName)
				.putParam("params", paramsString));
		return callSql;
	}

	/**
	 * <p>方法名：buildPagingSql</p>
	 * <p>描述：构建分页语句</p>
	 * <p>占位符：sql | pageIndex | pageLimit | startRow 下标从 1 开始 | startRowSubscript0 下标从 0 开始 | endRow 下标从 1 开始 | endRowSubscript0 下标从 0 开始</p>
	 * @param sql
	 * @param pageIndex 页数
	 * @param pageLimit 每页数据条数
	 * @return 分页语句
	 */
	public String buildPagingSql(String sql, int pageIndex, int pageLimit) {
		Page<Object> p = new Page<Object>(pageIndex, pageLimit);

		String pagingSql = ReadResource.getValue(this.resourceName, "buildPagingSql");
		pagingSql = PlaceholderCommons.replacePlaceholder(pagingSql, new ParamMap<String, String>()
				.putParam("sql", sql)
				.putParam("pageIndex", String.valueOf(pageIndex))
				.putParam("pageLimit", String.valueOf(pageLimit))
				.putParam("startRow", String.valueOf(p.getStartRow()))
				.putParam("startRowSubscript0", String.valueOf(p.getStartRowSubscript0()))
				.putParam("endRow", String.valueOf(p.getEndRow()))
				.putParam("endRowSubscript0", String.valueOf(p.getEndRowSubscript0())));
		return pagingSql;
	}

	/**
	 * <p>方法名：buildCountSql</p>
	 * <p>描述：构建计数语句</p>
	 * @param sql
	 * @return 计数语句
	 */
	public String buildCountSql(String sql) {
		String countSql = ReadResource.getValue(this.resourceName, "buildCountSql");
		countSql = PlaceholderCommons.replacePlaceholder(countSql, new ParamMap<String, String>()
				.putParam("sql", sql));
		return countSql;
	}

	/**
	 * <p>方法名：buildClearTableSql</p>
	 * <p>描述：构建清空表语句</p>
	 * @param tableName 表名
	 * @return 清空表语句
	 */
	public String buildClearTableSql(String tableName) {
		String clearSql = ReadResource.getValue(this.resourceName, "buildClearTableSql");
		clearSql = PlaceholderCommons.replacePlaceholder(clearSql, new ParamMap<String, String>()
				.putParam("tableName", tableName));
		return clearSql;
	}

	/**
	 * <p>方法名：buildCopyDataSql</p>
	 * <p>描述：构建拷贝数据语句，从 from 表拷贝 fromColumns 列到 to 表 toColumns 列</p>
	 * @param from
	 * @param fromColumns 默认为 *
	 * @param to
	 * @param toColumns 默认为空，当不为空时默认在生成的字符串头尾添加括号
	 * @param whereFragment where 条件片段，如果条件判断无 where 关键字，默认在头部添加 where 关键字
	 * @return 计数语句
	 */
	public String buildCopyDataSql(String from, List<String> fromColumns, String to, List<String> toColumns, String whereFragment) {
		String fromColumnsString = "*";
		if (ValidateCommons.isNotEmpty(fromColumns)) {
			fromColumnsString = StringCommons.merger(fromColumns.toArray(), ", ", true);
		}
		String toColumnsString = "";
		if (ValidateCommons.isNotEmpty(toColumns)) {
			toColumnsString = StringCommons.merger("(", StringCommons.merger(toColumns.toArray(), ", ", true), ")");
		}
		if (ValidateCommons.isNotEmpty(whereFragment) && !StringCommons.toLowerCase(whereFragment.trim()).startsWith("where")) {
			whereFragment = StringCommons.merger("where ", whereFragment);
		}

		String copyDataSql = ReadResource.getValue(this.resourceName, "buildCopyDataSql");
		copyDataSql = PlaceholderCommons.replacePlaceholder(copyDataSql, new ParamMap<String, String>()
				.putParam("from", from)
				.putParam("fromColumns", fromColumnsString)
				.putParam("to", to)
				.putParam("toColumns", toColumnsString)
				.putParam("whereFragment", whereFragment));
		return copyDataSql;
	}

}
